#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#define LOGX(flag, msg) logWrite(flag, msg, __FILE__, __FUNCTION__, __LINE__)

void logWrite(int flag, const char *msg, const char *file, const char *function, int line)
{
    const char* filename;
    switch(flag)
    {
        case ERROR:
            filename = "log_err.log";
            break;
        case INFO:
            filename = "log_info.log";
            break;
        case MESSAGE:
            filename = "log_msg.log";
            break;
        default:
            filename = "log.log";
            break;
    }

    // 打开日志文件
    int fd = open(filename, O_RDWR | O_APPEND | O_CREAT, 0644);
    if (fd < 0)
    {
        perror("open log failed");
        return;
    }

    // 组合日志信息
    char buff[1024];
    // 记录当前时间
    time_t now = time(NULL);
    struct tm *local_time = localtime(&now);
    strftime(buff, sizeof(buff), "[ %Y-%m-%d %H:%M:%S ]", local_time);
    snprintf(buff + strlen(buff), sizeof(buff) - strlen(buff),
             "[%s::%s::%d]: %s\n", file, function, line, msg);

    // 写入日志文件
    if (write(fd, buff, strlen(buff)) < 0)
    {
        perror("write log failed");
    }

    // 关闭日志文件
    close(fd);
}

void logClientConnection(user_info_t *user)
{
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);

    // 获取客户端地址信息
    if (getpeername(user->sockfd, (struct sockaddr*)&clientaddr, &len) < 0)
    {
        LOGX(ERROR, "getpeername failed");
        return;
    }

    // 拼接客户端地址信息
    char buff[1024];
    snprintf(buff, sizeof(buff), "client %s:%d connected.",
             inet_ntoa(clientaddr.sin_addr),
             ntohs(clientaddr.sin_port));

    // 写入日志
    LOGX(INFO, buff);
}

void logClientOperation(user_info_t *user, const char* operation)
{
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);

    if (getpeername(user->sockfd, (struct sockaddr*)&clientaddr, &len) < 0)
    {
        LOGX(ERROR, "getpeername failed");
        return;
    }

    char buff[1024];
    snprintf(buff, sizeof(buff), "client %s %s:%d : %s",
             user->name,
             inet_ntoa(clientaddr.sin_addr),
             ntohs(clientaddr.sin_port),
             operation);

    LOGX(INFO, buff);
}

